package com.ecar.api.support.util;

import com.ecar.common.util.HttpClientUtil;
import com.ecar.common.util.StringUtil;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Random;

/**
 * 微信授权登录工具类
 * Created by admin on 2016/7/6.
 */
public class WXLoginUtil {

	private static final Logger log = LoggerFactory.getLogger(WXLoginUtil.class);

	private static WXLoginUtil instance = new WXLoginUtil();

	private WXLoginUtil() { }

	public static WXLoginUtil getInstance() {
		return instance;
	}

	/**
	 * 获取公众号客户端token
	 * @return
	 */
	public String getClientToken() {
		try {
			String token = Redis.c.get(Redis.K.WX_TOKEN.me());
			if (StringUtil.isNotEmpty(token)) return token;

			String appId = Props.getValue("weixin.public.appid");
			String appSecret = Props.getValue("weixin.public.appsecret");
			String url = Props.getValue("weixin.api.token");
			url = MessageFormat.format(url, appId, appSecret);
			String json = HttpClientUtil.httpGet(url);
			JSONObject userToken = JSONObject.fromObject(json);
			if (!userToken.containsKey("access_token")) {
				json = HttpClientUtil.httpGet(url);
				userToken = JSONObject.fromObject(json);
				if (!userToken.containsKey("access_token")) return null;
			}
			token = (String) userToken.get("access_token");
			Redis.c.setex(Redis.K.WX_TOKEN.me(), 7000, token);
			return token;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取用户接口授权对象
	 * @param clientId
	 * @param clientSecret
	 * @param username
	 * @param password
	 * @return
	 */
	private JSONObject getUserToken(String clientId, String clientSecret, String username, String password) {
		try {
			String url = Props.getValue("oauth.password.url");
			url = MessageFormat.format(url, clientId, clientSecret, username, password);
			String json = HttpClientUtil.httpGet(url);
			JSONObject userToken = JSONObject.fromObject(json);
			if (userToken.containsKey("access_token")) {
				int expires = userToken.getInt("expires_in");
				if (expires <= 3600) {
					String refreshToken = userToken.getString("refresh_token");
					url = Props.getValue("oauth.refresh.url");
					url = MessageFormat.format(url, clientId, clientSecret, refreshToken);
					json = HttpClientUtil.httpGet(url);
					userToken = JSONObject.fromObject(json);
					if (!userToken.containsKey("access_token")) {
						userToken = null;
					}
				}
			} else {  // 获取两次，双重保险。
				json = HttpClientUtil.httpGet(url);
				userToken = JSONObject.fromObject(json);
				if (!userToken.containsKey("access_token")) {
					userToken = null;
				}
			}
			return userToken;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取IOS用户的接口授权对象
	 * @param username
	 * @param password
	 * @return
	 */
	public JSONObject getIosUserToken(String username, String password) {
		String clientId = Props.getValue("oauth.ios.client");
		String clientSecret = Props.getValue("oauth.ios.secret");
		return getUserToken(clientId, clientSecret, username, password);
	}

	/**
	 * 获取安卓用户的接口授权对象
	 * @param username
	 * @param password
	 * @return
	 */
	public JSONObject getAndUserToken(String username, String password) {
		String clientId = Props.getValue("oauth.and.client");
		String clientSecret = Props.getValue("oauth.and.secret");
		return getUserToken(clientId, clientSecret, username, password);
	}

	/**
	 * 获取WAP端用户的接口授权对象
	 * @param username
	 * @param password
	 * @return
	 */
	public JSONObject getWapUserToken(String username, String password) {
		String clientId = Props.getValue("oauth.wc.client");
		String clientSecret = Props.getValue("oauth.wc.secret");
		return getUserToken(clientId, clientSecret, username, password);
	}


	/**
	 * 获取微信公众号授权回调URI
	 * @return
	 */
	public URI getWxAuthRedirectURI(String state) {
		try {
			String appid = Props.getValue("weixin.public.appid");
			String redirect = Props.getValue("weixin.redirect.url");
			String url = Props.getValue("weixin.auth.url");
			url = MessageFormat.format(url, appid, redirect, state);
			return new URI(url);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取微信公众号授权回调URI
	 * @return
	 */
	public URI getWxAuthRedirectURI(String state, String param) {
		try {
			String appid = Props.getValue("weixin.public.appid");
			String redirect = Props.getValue("weixin.redirect.url") + param;
			String url = Props.getValue("weixin.auth.url");
			url = MessageFormat.format(url, appid, redirect, state);
			return new URI(url);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取快速下单授权跳转地址
	 * @param cacheKey
	 * @return
	 */
	public URI getWapFlashRedirectURI(String cacheKey) {
		try {
			String state = "0";
			String appid = Props.getValue("weixin.public.appid");
			String redirect = Props.getValue("weixin.redirect.url") + "?key=" + cacheKey;
			String url = Props.getValue("weixin.auth.url");
			url = MessageFormat.format(url, appid, redirect, state);
			return new URI(url);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取WAP端授权完成跳转地址
	 * @param openid
	 * @param userId
	 * @param accessToken
	 * @param phone
	 * @return
	 */
	public URI getWapUri(String openid, int userId, String accessToken, String phone, String refreshToken) {
		try {
			String url = Props.getValue("weixin.wap");
			url += Props.getValue("weixin.wap.index");
			url = MessageFormat.format(url, openid, String.valueOf(userId), accessToken, phone, refreshToken);
			log.debug("授权回调跳转地址：" + url);
			return new URI(url);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取快速下单班次查询跳转地址
	 * @param startId
	 * @param terminalId
	 * @return
	 */
	public URI getWapShiftUri(int startId, int terminalId, String startName, String startCity) {
		try {
			String now = String.valueOf(new Date().getTime());
			String url = Props.getValue("weixin.wap");
			url += Props.getValue("weixin.wap.shift");
			startName = URLEncoder.encode(startName, "utf-8");
			url = MessageFormat.format(url, now, String.valueOf(startId), String.valueOf(terminalId), startName, startCity);
			log.debug("快速下单班次查询跳转地址：" + url);
			return new URI(url);
		} catch (URISyntaxException | UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取快速下单跳转地址
	 * @return
	 */
	public URI getWapSubmitUri(String cacheKey, int userId, String accessToken, String refreshToken) {
		try {
			String url = Props.getValue("weixin.wap");
			url += Props.getValue("weixin.wap.submit");
			url = MessageFormat.format(url, URLEncoder.encode(cacheKey, "UTF-8"),
									   String.valueOf(userId), accessToken, refreshToken);
			log.debug("快速下单班次查询跳转地址：" + url);
			return new URI(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取未授权用户快速下单跳转地址
	 * @param openid
	 * @param cacheKey
	 * @return
	 */
	public URI getWapNoauthUri(String openid,JSONObject userinfo) {
		try {
			String unionid = userinfo.containsKey("unionid") ? userinfo.getString("unionid") : null;
			String device = "wechat";
			String deviceInfo = openid + "_WAP";
			String url = Props.getValue("weixin.wap");
			url += Props.getValue("weixin.wap.noauth");
			url +="?openid="+openid+"&unionid="+unionid+"&device="+device+"&deviceInfo="+deviceInfo;
//			url = MessageFormat.format(url, openid, "0", URLEncoder.encode(cacheKey, "UTF-8"));
			log.debug("快速下单班次查询跳转地址：" + url);
			return new URI(url);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 快速下单无班次跳转地址
	 * @return
	 */
	public URI getWap404Uri() {
		try {
			String url = Props.getValue("weixin.wap");
			url += Props.getValue("weixin.wap.404");
			String msg = Props.getValue("weixin.wap.msg");
			msg = URLEncoder.encode(msg, "UTF-8");
			url = MessageFormat.format(url, msg);
			log.debug("快速下单无班次跳转地址：" + url);
			return new URI(url);
		} catch (URISyntaxException | UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	public URI getWapMessageUri(String msg) {
		try {
			String url = Props.getValue("weixin.wap") + Props.getValue("weixin.wap.404");
			msg = URLEncoder.encode(msg, "UTF-8");
			url = MessageFormat.format(url, msg);
			log.info("跳转提示：" + url);
			return new URI(url);
		} catch (URISyntaxException | UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取微信公众号的ACCESS TOKEN对象
	 * @param code
	 * @return
	 */
	public JSONObject getAccessToken(String code) {
		String appid = Props.getValue("weixin.public.appid");
		String appsecret = Props.getValue("weixin.public.appsecret");
		String url = Props.getValue("weixin.accesstoken.url");
		url = MessageFormat.format(url, appid, appsecret, code);
		log.debug("获取accesstoken: " + url);
		String json = HttpClientUtil.httpGet(url);
		log.debug("结果: " + json);
		return JSONObject.fromObject(json);
	}

	/**
	 * 获取微信用户资料
	 * @param accessToken
	 * @param openid
	 * @return
	 */
	public JSONObject getUserInfo(String accessToken, String openid) {
		String url = Props.getValue("weixin.userinfo.url");
		url = MessageFormat.format(url, accessToken, openid);
		log.debug("获取用户信息: " + url);
		String json = HttpClientUtil.httpGet(url);
		log.debug("结果: " + json);
		return JSONObject.fromObject(json);
	}

	public JSONObject createQr(int agencyId) {
		if (Props.isDebug()) return createTempQr(agencyId);
		try {
			String token = getClientToken();
			if (StringUtil.isEmpty(token)) return null;

			String scene = "{\"scene\": {\"scene_id\": "+agencyId+"}}";
			JSONObject params = new JSONObject();
			params.put("action_name", "QR_LIMIT_SCENE");
			params.put("action_info", JSONObject.fromObject(scene));
			String url = Props.getValue("weixin.api.createqr");
			url = MessageFormat.format(url, token);
			String response = HttpClientUtil.httpPostContent(url, params.toString());
			log.debug("创建永久二维码: {}", response);
			JSONObject result = JSONObject.fromObject(response);
			if (!result.containsKey("ticket")) return null;
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public JSONObject createQr(String sceneStr) {
		if (Props.isDebug()) return createTempQr(new Random().nextInt(999999));
		try {
			String token = getClientToken();
			if (StringUtil.isEmpty(token)) return null;

			String scene = "{\"scene\": {\"scene_str\": \"" + sceneStr + "\"}}";
			JSONObject params = new JSONObject();
			params.put("action_name", "QR_LIMIT_STR_SCENE");
			params.put("action_info", JSONObject.fromObject(scene));
			String url = Props.getValue("weixin.api.createqr");
			url = MessageFormat.format(url, token);
			String response = HttpClientUtil.httpPostContent(url, params.toString());
			log.debug("创建永久二维码: {}", response);
			JSONObject result = JSONObject.fromObject(response);
			if (!result.containsKey("ticket")) return null;
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public JSONObject createTempQr(int sceneId) {
		try {
			String token = getClientToken();
			if (StringUtil.isEmpty(token)) return null;

			String scene = "{\"scene\": {\"scene_id\": " + sceneId + "}}";
			JSONObject params = new JSONObject();
			params.put("action_name", "QR_SCENE");
			params.put("expire_seconds", 2592000);
			params.put("action_info", JSONObject.fromObject(scene));
			String url = Props.getValue("weixin.api.createqr");
			url = MessageFormat.format(url, token);
			String response = HttpClientUtil.httpPostContent(url, params.toString());
			log.debug("创建临时二维码: {}", response);
			JSONObject result = JSONObject.fromObject(response);
			if (!result.containsKey("ticket")) return null;
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public String sendTextMsg(String content, String touser) {
		try {
			String url = MessageFormat.format(Props.getValue("weixin.msg.url"), getClientToken());
			JSONObject text = new JSONObject();
			text.put("content", content);

			JSONObject msg = new JSONObject();
			msg.put("touser", touser);
			msg.put("msgtype", "text");
			msg.put("text", text);
			return HttpClientUtil.httpPostContent(url, msg.toString());
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
